﻿using AutoMapper;
using QYmall.Core.Common.Emum;
using QYmall.Core.Common.Helper;
using QYmall.Core.DBFactory.Database;
using QYmall.Core.IServices;
using QYmall.Core.Model.Models;
using QYmall.Core.Model.ViewModels;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace QYmall.Core.Services
{
    /// <summary>
    /// 限时抢购接口实现
    /// </summary>
    public class ShopSkuService : BaseService, IShopSkuService
    {
        private readonly IUserService _userService;
        private readonly IMapper _mapper;

        public ShopSkuService(IDbContextFactory contentFactory,
            IUserService userService, IMapper mapper) : base(contentFactory)
        {
            _userService = userService;
            _mapper = mapper;
        }

        /// <summary>
        /// 根据条件获取一条记录
        /// </summary>
        public async Task<ShopSkusDto?> QueryAsync(Expression<Func<ShopSkus, bool>> funcWhere,
            WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            //获取一条规格信息
            var model = await _context.Set<ShopSkus>().Where(x => x.ParentId == 0).FirstOrDefaultAsync(funcWhere);
            if (model == null)
            {
                return null;
            }
            //获取规格值列表
            var modelt = await _context.Set<ShopSkus>().Where(x => x.ParentId == model.Id).ToListAsync();
            //映射成DTO
            var result = _mapper.Map<ShopSkusDto>(model);
            //映射并赋值列表
            result.Children = _mapper.Map<ICollection<ShopSkusChildrenDto>>(modelt);

            return result;
        }

        /// <summary>
        /// 查询所有数据列表
        /// </summary>
        public async Task<IEnumerable<ShopSkusDto>> QueryListAsync(int top, Expression<Func<ShopSkus, bool>> funcWhere,
            WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            List<ShopSkusDto> result = new();
            var list = await _context.Set<ShopSkus>().Where(funcWhere).ToListAsync();
            var parentList = list.Where(x => x.ParentId == 0).OrderBy(x => x.SortId);
            foreach (var modelt in parentList)
            {
                var modeltDto = _mapper.Map<ShopSkusDto>(modelt);
                var models = list.Where(x => x.ParentId == modelt.Id).OrderBy(x => x.SortId);
                modeltDto.Children = _mapper.Map<ICollection<ShopSkusChildrenDto>>(models);
                result.Add(modeltDto);
            }
            if (top > 0) result = result.Take(top).ToList();//等于0显示所有数据
            return result;
        }

        /// <summary>
        /// 添加一条记录
        /// </summary>
        public async Task<ShopSkus> AddAsync(ShopSkusEditDto modelDto, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            //映射成源数据
            var model = _mapper.Map<ShopSkus>(modelDto);
            //记录当前用户名
            model.AddBy = await _userService.GetUserNameAsync();
            model.AddTime = DateTime.Now;
            var childrenlList = _mapper.Map<ICollection<ShopSkus>>(modelDto.Children);

            //开启事务
            using (var transaction = await _context.Database.BeginTransactionAsync())
            {
                try
                {
                    //保存规格信息
                    await _context.Set<ShopSkus>().AddAsync(model);
                    await this.SaveAsync();
                    //新增规格值
                    foreach (var modelt in childrenlList)
                    {
                        modelt.ParentId = model.Id;//父规格ID
                        modelt.MerchantId = model.MerchantId;
                    }
                    //赋值之后批量添加
                    await _context.Set<ShopSkus>().AddRangeAsync(childrenlList);
                    await this.SaveAsync();
                    //提交事务
                    await transaction.CommitAsync();
                }
                catch
                {
                    //回滚事务
                    await transaction.RollbackAsync();
                    throw new ResponseException("保存时发生意外错误");
                }
            }
            return model;
        }

        /// <summary>
        /// 修改一条记录
        /// </summary>
        public async Task<bool> UpdateAsync(long id, ShopSkusEditDto modelDto, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            //根据ID获取记录
            var model = await _context.Set<ShopSkus>().Where(x => x.ParentId == 0 && x.Id == id).FirstOrDefaultAsync();
            //如果不存在则抛出异常
            if (model == null)
            {
                throw new ResponseException("规格不存在或已删除");
            }

            //如果没有规格值则全部删除
            if (modelDto.Children == null || modelDto.Children.Count == 0)
            {
                //删除所有的规格值
                var removeList = await _context.Set<ShopSkus>().Where(x => x.ParentId == id).ToListAsync();
                _context.Set<ShopSkus>().RemoveRange(removeList);
            }
            else
            {
                //将DTO转换成源数据列表
                var list = _mapper.Map<ICollection<ShopSkus>>(modelDto.Children);
                var listIds = list.Where(x => x.Id > 0).Select(x => x.Id);
                //删除已移除的规格值
                var removeList = await _context.Set<ShopSkus>().Where(x => x.ParentId == id && !listIds.Contains(x.Id)).ToListAsync();
                _context.Set<ShopSkus>().RemoveRange(removeList);
                //如果ID大于0则修改，否则添加
                foreach (var modelt in list)
                {
                    modelt.ParentId = model.Id;//将父ID设置为规格ID
                    modelt.MerchantId = model.MerchantId;
                    if (modelt.Id > 0)
                    {
                        //修改
                        _context.Set<ShopSkus>().Update(modelt);
                    }
                    else
                    {
                        //添加
                        await _context.Set<ShopSkus>().AddAsync(modelt);
                    }
                }
            }
            //将DTO映射到源数据
            _mapper.Map(modelDto, model);
            _context.Set<ShopSkus>().Update(model);
            //全部提交保存
            return await this.SaveAsync();
        }
    }
}
